GAME_WINDOW = document.getElementById('mainContainer')
GAME_WINDOW_CONTEXT = GAME_WINDOW.getContext('2d')
GAME_HIDDEN_ELEMENTS_CONTAINER = document.getElementById('hiddenElementsContainer')

GAME_WINDOW_WIDTH = 800
GAME_WINDOW_HEIGHT = 600
GAME_WINDOW_SCALE = .25
GAME_WINDOW_SCALE_INVERSE = 4

// Set window size

function setSize() {
	let pageWidth = document.documentElement.clientWidth
	let pageHeight = document.documentElement.clientHeight
	GAME_WINDOW_SCALE = Math.min(pageWidth / GAME_WINDOW_WIDTH, pageHeight / GAME_WINDOW_HEIGHT)
	GAME_WINDOW_SCALE_INVERSE = 1 / GAME_WINDOW_SCALE
	GAME_WINDOW.width = GAME_WINDOW_SCALE * GAME_WINDOW_WIDTH
	GAME_WINDOW.height = GAME_WINDOW_SCALE * GAME_WINDOW_HEIGHT
}

setSize()
window.onresize = setSize

// Keyboard manager

KEYBOARD_STATE = {}

window.addEventListener('keydown', function (event) {
	KEYBOARD_STATE[event.code] = true
})
window.addEventListener('keyup', function (event) {
	KEYBOARD_STATE[event.code] = undefined
})

// Mouse manager

MOUSE_STATE = { in: true, click: false, x: undefined, y: undefined }

GAME_WINDOW.addEventListener('mouseenter', function (event) {
	event.preventDefault()
	MOUSE_STATE.in = true
	MOUSE_STATE.x = event.offsetX * GAME_WINDOW_SCALE_INVERSE
	MOUSE_STATE.y = event.offsetY * GAME_WINDOW_SCALE_INVERSE
})
GAME_WINDOW.addEventListener('mouseleave', function (event) {
	event.preventDefault()
	MOUSE_STATE.click = false
	MOUSE_STATE.in = false
})
GAME_WINDOW.addEventListener('mousemove', function (event) {
	event.preventDefault()
	MOUSE_STATE.x = event.offsetX * GAME_WINDOW_SCALE_INVERSE
	MOUSE_STATE.y = event.offsetY * GAME_WINDOW_SCALE_INVERSE
})
GAME_WINDOW.addEventListener('mousedown', function (event) {
	event.preventDefault()
	MOUSE_STATE.in = true
	MOUSE_STATE.click = true
	MOUSE_STATE.x = event.offsetX * GAME_WINDOW_SCALE_INVERSE
	MOUSE_STATE.y = event.offsetY * GAME_WINDOW_SCALE_INVERSE
})
GAME_WINDOW.addEventListener('mouseup', function (event) {
	event.preventDefault()
	MOUSE_STATE.click = false
	MOUSE_STATE.x = event.offsetX * GAME_WINDOW_SCALE_INVERSE
	MOUSE_STATE.y = event.offsetY * GAME_WINDOW_SCALE_INVERSE
})
GAME_WINDOW.addEventListener('touchstart', function (event) {
	event.preventDefault()
	if (event.touches.length) {
		let touch = event.touches[0]
		MOUSE_STATE.in = true
		MOUSE_STATE.click = true
		MOUSE_STATE.x = (touch.pageX - GAME_WINDOW.offsetLeft) * GAME_WINDOW_SCALE_INVERSE
		MOUSE_STATE.y = (touch.pageY - GAME_WINDOW.offsetTop) * GAME_WINDOW_SCALE_INVERSE
	}
})
GAME_WINDOW.addEventListener('touchmove', function (event) {
	event.preventDefault()
	if (event.touches.length) {
		let touch = event.touches[0]
		MOUSE_STATE.in = true
		MOUSE_STATE.x = (touch.pageX - GAME_WINDOW.offsetLeft) * GAME_WINDOW_SCALE_INVERSE
		MOUSE_STATE.y = (touch.pageY - GAME_WINDOW.offsetTop) * GAME_WINDOW_SCALE_INVERSE
	}
})
GAME_WINDOW.addEventListener('touchend', function (event) {
	event.preventDefault()
	MOUSE_STATE.click = false
	MOUSE_STATE.in = false
})
GAME_WINDOW.addEventListener('touchcancel', function (event) {
	event.preventDefault()
	MOUSE_STATE.click = false
	MOUSE_STATE.in = false
})

// Image manager

GAME_IMAGE_MANAGER = {}

function loadImage(src) {
	if (GAME_IMAGE_MANAGER[src] === undefined) {
		let img = new Image()
		img.src = src
		GAME_IMAGE_MANAGER[src] = img
		return img
	} else
		return GAME_IMAGE_MANAGER[src]
}

// Audio manager

GAME_AUDIO_MANAGER = []

function playAudio(src, loop = false) {
	let audio = new Audio()
	audio.crossOrigin = 'anonymous'
	audio.src = src
	if (loop)
		audio.loop = 'loop'
	GAME_AUDIO_MANAGER.push(audio)
	audio.autoplay = true
}

function stopAllAudio() {
	GAME_AUDIO_MANAGER.forEach(function (audio) {
		audio.pause()
	})
	GAME_AUDIO_MANAGER = []
}

// Drawing functions

function strokeRect(x, y, width, height, option = {}) {
	let lineWidth = option.lineWidth ? option.lineWidth : 1
	let stroke = option.stroke ? option.stroke : '#FFF'

	GAME_WINDOW_CONTEXT.strokeStyle = stroke
	GAME_WINDOW_CONTEXT.lineWidth = lineWidth * GAME_WINDOW_SCALE
	GAME_WINDOW_CONTEXT.strokeRect(x * GAME_WINDOW_SCALE, y * GAME_WINDOW_SCALE, width * GAME_WINDOW_SCALE, height * GAME_WINDOW_SCALE)
}

function fillRect(x, y, width, height, option = {}) {
	let fill = option.fill ? option.fill : '#000'

	GAME_WINDOW_CONTEXT.fillStyle = fill
	GAME_WINDOW_CONTEXT.fillRect(x * GAME_WINDOW_SCALE, y * GAME_WINDOW_SCALE, width * GAME_WINDOW_SCALE, height * GAME_WINDOW_SCALE)
}

function strokeLine(x, y, x2, y2, option = {}) {
	let lineWidth = option.lineWidth ? option.lineWidth : 1
	let stroke = option.stroke ? option.stroke : '#FFF'

	GAME_WINDOW_CONTEXT.strokeStyle = stroke
	GAME_WINDOW_CONTEXT.lineWidth = lineWidth * GAME_WINDOW_SCALE
	GAME_WINDOW_CONTEXT.beginPath()
	GAME_WINDOW_CONTEXT.moveTo(x * GAME_WINDOW_SCALE, y * GAME_WINDOW_SCALE)
	GAME_WINDOW_CONTEXT.lineTo(x2 * GAME_WINDOW_SCALE, y2 * GAME_WINDOW_SCALE)
	GAME_WINDOW_CONTEXT.stroke()
}

function fillText(text, x, y, option = {}) {
	let fill = option.fill ? option.fill : '#FFF'
	let fontSize = option.fontSize ? option.fontSize : 20
	fontSize *= GAME_WINDOW_SCALE
	let font = option.font ? option.font : 'Bahnschrift'
	let alignX = option.alignX ? option.alignX : 'center'
	let alignY = option.alignY ? option.alignY : 'middle'

	GAME_WINDOW_CONTEXT.fillStyle = fill
	GAME_WINDOW_CONTEXT.font = fontSize.toFixed(0) + 'px ' + font
	GAME_WINDOW_CONTEXT.textAlign = alignX
	GAME_WINDOW_CONTEXT.textBaseline = alignY
	GAME_WINDOW_CONTEXT.fillText(text, x * GAME_WINDOW_SCALE, y * GAME_WINDOW_SCALE)
}

function drawImage(src, x, y, width, height, option = {}) {
	let img = loadImage(src)
	GAME_WINDOW_CONTEXT.drawImage(img, x * GAME_WINDOW_SCALE, y * GAME_WINDOW_SCALE, width * GAME_WINDOW_SCALE, height * GAME_WINDOW_SCALE)
}

function drawGlitch(x, y, width, height, option = {}) {
	let glitch = option.glitch ? option.glitch : 1

	glitch *= 500
	let colors = ['#FFFFFF80', '#FFFFFF40', '#FFFFFF20']
	for (let i = 0; i < glitch; ++i)
		fillRect(x + Math.random() * (width - 20), y + Math.random() * height, 20, 1 + Math.random() * 4, option = { fill: colors[Math.floor(Math.random() * 3)] })
}

// UI functions

function uiRectButton(x, y, width, height, option = {}) {
	if (MOUSE_STATE.x >= x && MOUSE_STATE.x <= x + width && MOUSE_STATE.y >= y && MOUSE_STATE.y <= y + height) {
		if (option.hoverClick || MOUSE_STATE.click) {
			fillRect(x, y, width, height, { fill: option.fillClick })
			strokeRect(x, y, width, height, { stroke: option.stroke })
			return true
		} else {
			fillRect(x, y, width, height, { fill: option.fillHover })
			strokeRect(x, y, width, height, { stroke: option.stroke })
			return false
		}
	} else {
		fillRect(x, y, width, height, { fill: option.fill })
		strokeRect(x, y, width, height, { stroke: option.stroke })
		return false
	}
}
function uiIntegerSelector(data, x, y, option = {}) {
	let min = option.min !== undefined ? option.min : 0
	let max = option.max !== undefined ? option.max : 20
	let defaultValue = option.defaultValue !== undefined ? option.defaultValue : 0

	if (data.value === undefined)
		data.value = defaultValue

	// Draw - button
	if (uiRectButton(x + 5, y + 5, 40, 40, option)) {
		if (!data.leftClick) {
			data.leftClick = true
			if (data.value >= min + 1)
				--data.value
		}
	} else
		data.leftClick = undefined
	fillText('-', x + 25, y + 24, { fontSize: 48 })

	// Draw value
	fillText(data.value.toFixed(0), x + 100, y + 26, { fontSize: 72 })

	// Draw + button
	if (uiRectButton(x + 155, y + 5, 40, 40, option)) {
		if (!data.rightClick) {
			data.rightClick = true
			if (data.value + 1 <= max)
				++data.value
		}
	} else
		data.rightClick = undefined
	fillText('+', x + 175, y + 26, { fontSize: 48 })
}